💡 论文解读与参考来源:本文内容基于对微软论文 From Local to Global: A Graph RAG Approach to Query-Focused Summarization (arXiv:2404.16130) 的深入研读、工程实践与架构解读。
已完成 GraphRAG 构建后,检索阶段的核心目标不是重新构建图,而是根据已生成的图谱、社区和摘要,完成:
也就是说,检索阶段只依赖已构建出的索引对象,而不重复执行实体抽取和社区构建。
在已构建好的 GraphRAG 中,通常至少存在以下数据:
entities:实体表entity_aliases:实体别名表edges:关系边与权重communities:社区表community_members:社区包含哪些实体community_summaries:每个社区的摘要claims:事实声明 / 证据检索部分只需要使用这些结构,不需要再走文档抽取流程。
GraphRAG 的检索并不是“全部由 LLM 完成”,而是“规则/索引计算 + LLM 语义增强”的混合结构。
MERMAID
用户输入一个问题后,先做:
例如:
text查询:A 和 B 的合作背景是什么?
可抽取的信号:
这里通常可以由 LLM 负责,但也可以在一部分系统中用规则 + embedding 预先优化。
通过下面几种方式多路命中候选实体,并利用 RRF(Reciprocal Rank Fusion) 或权重融合多路命中结果:
多路命中列表通过 RRF 融合后,得到按综合置信度排序的查询相关实体集:
从命中的实体出发,向图中扩展一层邻居:
这里的 是图中实体之间存在的边集合。这样可以扩大召回范围,把“显性命中”扩展成“相关主题命中”。
把扩展后的实体映射回社区:
其中:
这一步的核心目的,是把“实体检索”转换成“社区召回”。
对候选社区打分,排序后取 Top-K。打分方式支持加权综合得分或 RRF(倒数排名融合):
方式 1:加权综合评分
其中:
方式 2:RRF 异构排名融合 由于语义相似度(余弦值)、实体重叠率(0~1)与图拓扑得分(无界计数值)量纲差异大且难以人工确定最佳权重,可分别生成三路排名列表,再通过 RRF 进行无量纲融合:
最终排序本身是基于结构化数值计算,由 Top-K 结果进入下一步。
在社区排序完成后,通常还会有一个 LLM 参与的“再筛选”步骤:
这一步的本质不是重新构建图,而是对已排序社区做语义再判定。
最终返回 Top-K 社区,并附带:
这些信息可以直接作为答案生成的上下文。
图边的权重是关系被重复确认的强度:
其中:
这意味着:
社区命中文本的一个简单判断方式是:
它衡量的是:查询实体和社区实体之间的覆盖程度。
图结构得分可由边权重和邻居密度来估算:
如果社区中包含大量与查询实体强连接的邻居,那么它更可能成为高质量检索结果。
当存在多路异构打分渠道(如向量相似度、关键词精确匹配、图拓扑结构度数等)时,为避免复杂的跨量纲归一化和人工调权,使用 RRF 将各维度的排名直接融合:
其中:
LLM 在 GraphRAG 检索中并不是“全流程必经”,但在以下关键节点通常需要接入:
LLM 适合做:
例如:
text查询:A 和 B 为什么会在近几个月发生合作?
LLM 可以帮助判断:
LLM 可以把查询变成更适合召回的表达:
如果查询是:
text“它的历史沿革”
LLM 可以推断其可能指向:
这会让检索更接近用户真实意图。
即使候选社区已经按打分排序,LLM 仍然可以在候选集合上做一次“语义再判定”:
其作用是:
召回后的最终步骤,本质上是“基于社区摘要的回答生成”:
这里 LLM 负责:
这一步通常不再是检索本身,而是“基于检索结果的生成”。
不建议直接对所有社区做全文相似度扫描。更稳定的顺序是:
这样更符合 GraphRAG 的结构化检索思路。
社区摘要是“压缩后的专题信息”,比原始文档更适合做召回和排序。原因是:
仅看文本相似度可能漏掉:
因此在 GraphRAG 检索中,图结构是关键的非文本信号。
检索阶段不需要:
只要直接使用已构建好的数据即可。
在完成索引构建后,最小可用检索接口可以设计成以下几类:
tstype RetrievalRequest = { query: string; topK?: number; }; type CommunityHit = { communityId: string; score: number; summary: string; matchedEntities: string[]; };
返回:
tstype CommunityDetailsRequest = { communityId: string; };
返回:
tstype EntityNeighborsRequest = { entityName: string; depth?: number; };
返回:
最稳妥的检索实现顺序是:
query -> entity 匹配entity -> community 召回community -> summary 排序summary -> answer 生成该顺序最符合 GraphRAG 的数据流,也最容易与已有构建结果对接。
GraphRAG 的检索不是传统全文搜索,而是“基于已构建知识图的主题召回”:
这正是 GraphRAG 检索的核心实现思路。
typescriptfunction aggregateEdges(edges: Edge[]): AggregatedEdge[] { const existing = map.get(key); if (existing) { existing.weight += 1; } else { map.set(key, { sourceEntityId: item.sourceEntityId, targetEntityId: item.targetEntityId, relationType, weight: 1, }); } return Array.from(map.values()); } function scoreCommunity(query: string, communitySummary: string, entityNames: string[]): number { const semanticScore = similarity(query, communitySummary); const entityScore = entityNames.reduce((sum, entity) => sum + similarity(query, entity), 0); return semanticScore + 0.5 * entityScore; } function reciprocalRankFusion<T>(rankedLists: T[][], getId: (item: T) => string, k = 60): Array<{ item: T; score: number }> { const scoreMap = new Map<string, { item: T; score: number }>(); for (const list of rankedLists) { list.forEach((item, index) => { const id = getId(item); const rank = index + 1; const current = scoreMap.get(id); const rrfScore = 1 / (k + rank); if (current) { current.score += rrfScore; } else { scoreMap.set(id, { item, score: rrfScore }); } }); } return Array.from(scoreMap.values()).sort((a, b) => b.score - a.score); }
这个伪代码体现了三个关键点:
从 GraphRAG 的角度,文档中的“检索”可以概括为以下统一表达:
MERMAID
它与传统检索的关键差异在于:
因此,真正的检索价值并不只在“命中某一段文档”,而在于:
GraphRAG 下的文档检索,本质上是利用“文档 → 实体/关系/声明 → 知识图 → 社区摘要”的流程,先在大规模语义网络中定位主题,再通过图结构和摘要聚合生成最终答案。这种实现更适合复杂、抽象、跨文档的查询场景。